import axios, { AxiosInstance, AxiosResponse } from 'axios';
import { message } from 'ant-design-vue';
import { getLocal, getTokenKey } from '@/util/utils';

export class AxiosDownFileInstanceWrapper {
  private instance: AxiosInstance;
  /**
   * 是否需要等到
   * @param idLoading
   */
  constructor() {
    this.instance = new AxiosDownFileClient().getInstance()
  }

  public get(url: string, value?: any):Promise<AxiosResponse<void>> {
    if (value) {
      return <Promise<AxiosResponse<void>>>this.instance.get(url, { params: value })
    }
    return <Promise<AxiosResponse<void>>>this.instance.get(url)
  }

  public post(url: string, value: any):Promise<AxiosResponse<void>> {
    return <Promise<AxiosResponse<void>>>this.instance.post(url, value)
  }
}


class AxiosDownFileClient {
  private instance: AxiosInstance;

  constructor() {
    // 创建axios实例
    this.instance = axios.create({ timeout: 1000 * 1000 });
    // 初始化拦截器
    this.initInterceptors();
  }

  // 为了让http.ts中获取初始化好的axios实例
  public getInstance() {
    return this.instance;
  }


  // 初始化拦截器
  public initInterceptors() {
    // 设置post请求头
    this.instance.defaults.headers.post['Content-Type'] = 'application/json';
    /**
     * 请求拦截器
     * 每次请求前，如果存在token则在请求头中携带token
     */
    this.instance.interceptors.request.use(
      (config) => {
				const tokenKey = getTokenKey()
        const token = getLocal(tokenKey);
        if (token && typeof token === 'string') {
          if (!config.headers) {
            config.headers = {}
          }
          config.headers[tokenKey] = token
        }
        return config;
      },
      (error) => {
        message.error(error)
        console.log(error)
      },
    );

    this.instance.interceptors.response.use(
      (res) => {
        // 切割出文件名
        const fileNameEncode = res.headers['content-disposition'].split('fileName=')[1]
        // 解码
        const fileName = decodeURIComponent(fileNameEncode)

        //处理文档流
        const blob = new Blob([res.data]);
        const elink = document.createElement('a');
        elink.download = fileName;
        elink.style.display = 'none';
        elink.href = URL.createObjectURL(blob);
        document.body.appendChild(elink);
        elink.click();
        // 释放URL 对象
        URL.revokeObjectURL(elink.href);
        return Promise.resolve();
      },
      (error) => {
        const { response } = error;
        if (response) {
          // 请求已发出，但是不在2xx的范围
          this.errorHandle(response);
          return Promise.reject(response);
        } else {
          // 处理断网的情况
          // eg:请求超时或断网时，更新state的network状态
          // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
          // 关于断网组件中的刷新重新获取数据，会在断网组件中说明
          // ElMessage.warning!('网络连接异常,请稍后再试!');
          message.error('网络连接异常,请稍后再试!');
          return Promise.resolve({data:{success:false}});
        }
      }
    )
  }

  /**
   * http握手错误
   * @param res  响应回调,根据不同响应进行不同操作
   */
  private errorHandle(res: any) {
    // 状态码判断
    switch (res.status) {
      case 401:
        break;
      case 403:
        break;
      case 404:
        message.error('请求的资源不存在');
        break;
      default:
        message.error('网连接错误');
    }
  }
}
